/**
 * 
 */
package org.statewalker.validator;

import org.statewalker.fsm.providers.conf.IFsmTransitionsConfigurator;

public abstract class AbstractGrammar {

    private final IFsmTransitionsConfigurator<IParseKey, IParseKey> fConfig;

    private IParseKey fRoot;

    private AbstractValidator<?, ?> fValidator;

    public AbstractGrammar(AbstractValidator<?, ?> validator) {
        this(validator, null);
    }

    public AbstractGrammar(AbstractValidator<?, ?> validator, IParseKey root) {
        fValidator = validator;
        fRoot = root != null ? root : validator.getROOT();
        fConfig = validator.getFsmConfigurator();
        defineParent(getINITIAL(), getROOT());
        defineParent(getFINAL(), getROOT());
    }

    protected void defineMandatoryTransition(
        IParseKey key,
        IParseKey from,
        IParseKey to) {
        fConfig.beginState(key);
        fConfig.onTransition(from, getANY(), to);
        fConfig.onTransition(from, getFINAL(), to);
        fConfig.endState();
    }

    protected void defineParent(IParseKey child, IParseKey parent) {
        if (parent == null)
            return;
        // fConfig.beginState(parent);
        // fConfig.onDefaultTransition(child, child);
        // fConfig.endState();
        child.setParent(parent);
    }

    protected void defineSubstates(IParseKey key, IParseKey... children) {
        fConfig.beginState(key);
        for (IParseKey child : children) {
            fConfig.onDefaultTransition(child, child);
        }
        fConfig.endState();
    }

    protected void defineTransition(
        IParseKey key,
        IParseKey tokenKey,
        IParseKey targetKey) {
        fConfig.beginState(key);
        fConfig.onDefaultTransition(tokenKey, targetKey);
        fConfig.endState();
    }

    protected void defineTransition(
        IParseKey key,
        IParseKey from,
        IParseKey token,
        IParseKey to) {
        fConfig.beginState(key);
        fConfig.onTransition(from, token, to);
        fConfig.endState();
    }

    public IParseKey getANY() {
        return fValidator.getROOT();
    }

    public IParseKey getERROR() {
        return fValidator.getERROR();
    }

    public IParseKey getFINAL() {
        return fValidator.getFINAL();
    }

    public IParseKey getINITIAL() {
        return fValidator.getINITIAL();
    }

    public IParseKey getROOT() {
        return fRoot;
    }

    public AbstractValidator<?, ?> getValidator() {
        return fValidator;
    }

    public abstract void init();

    public IParseKey newKey(String name) {
        IParseKey key = fValidator.newParseKey(name);
        fConfig.beginState(key);
        fConfig.onDefaultTransition(getFINAL(), getFINAL());
        fConfig.endState();
        return key;
    }

}